package com.adv.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * XML解析工具类
 * 
 * @author WUQINGLONG
 *
 */
public class XmlUtil {

	private static final Logger logger = LoggerFactory.getLogger(XmlUtil.class);

	public static void main(String[] args) {
		// System.out.println(parse("e:/xxx.xml", new UpcFile()));
	}

	public static <T> T parse(InputStream inputStream, final T entity) {
		try {
			final Map<String, Field> map = new HashMap<String, Field>();
			for (Field field : entity.getClass().getDeclaredFields()) {
				XmlElement annotation = field.getAnnotation(XmlElement.class);
				if (null != annotation) {
					map.put(annotation.name(), field);
				} else {
					map.put(field.getName(), field);
				}
			}

			SAXParserFactory saxfac = SAXParserFactory.newInstance();
			SAXParser saxparser = saxfac.newSAXParser();
			saxparser.parse(inputStream, new DefaultHandler() {
				private String preTag;

				public void startDocument() throws SAXException {
				}

				public void endDocument() throws SAXException {
				}

				public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
					preTag = qName;
				}

				public void endElement(String uri, String localName, String qName) throws SAXException {
					preTag = null;
				}

				public void characters(char[] ch, int start, int length) throws SAXException {
					String node = new String(ch, start, length);
					Field field = map.get(preTag);
					if (null == field) {
						return;
					}
					if (Date.class.getName().equals(field.getType().getName())) {
						XmlElement annotation = field.getAnnotation(XmlElement.class);
						if (null != annotation && !annotation.defaultValue().equals("\u0000")) {
							SimpleDateFormat sdf = new SimpleDateFormat(annotation.defaultValue());
							try {
								field.setAccessible(true);
								field.set(entity, sdf.parse(node));
							} catch (ParseException | IllegalArgumentException | IllegalAccessException e) {
								logger.error("反射赋值错误 " + entity.getClass() + "." + field.getName());
								logger.error("反射赋值错误 " + e.getMessage());
								e.printStackTrace();
							}
						}
					} else if (Long.class.getName().equals(field.getType().getName())) {
						try {
							field.setAccessible(true);
							field.set(entity, Long.valueOf(node));
						} catch (IllegalArgumentException | IllegalAccessException e) {
							logger.error("反射赋值错误 " + entity.getClass() + "." + field.getName());
							logger.error("反射赋值错误 " + e.getMessage());
							e.printStackTrace();
						}
					} else {
						try {
							field.setAccessible(true);
							field.set(entity, node);
						} catch (IllegalArgumentException | IllegalAccessException e) {
							logger.error("反射赋值错误 " + entity.getClass() + "." + field.getName());
							logger.error("反射赋值错误 " + e.getMessage());
							e.printStackTrace();
						}
					}
				}
			});
		} catch (Exception e) {
			logger.error("解析文档错误 " + e.getMessage());
			e.printStackTrace();
		}
		return entity;
	}

	public static <T> T parse(String filepath, final T entity) {
		try {
			return parse(new FileInputStream(filepath), entity);
		} catch (FileNotFoundException e) {
			logger.error("解析文档错误 " + filepath);
			logger.error("解析文档错误 " + e.getMessage());
			e.printStackTrace();
		}
		return null;
	}
}
